package org.iabako.client.ui.form.business.product;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.ListBox;
import org.iabako.client.config.page.PageConfigEnum;
import org.iabako.client.navigation.NavigationController;
import org.iabako.client.tools.IabakoAsyncCallback;
import org.iabako.client.tools.Messages;
import org.iabako.client.ui.form.AbstractForm;
import org.iabako.client.ui.layout.field.*;
import org.iabako.client.ui.layout.template.Popup;
import org.iabako.client.ui.layout.widget.validation.ValidationMessage;
import org.iabako.client.ui.page.business.product.ProductCreate;
import org.iabako.client.ui.page.business.product.ProductSearch;
import org.iabako.client.user.AuthenticateUserProvider;
import org.iabako.shared.entity.business.AbstractEntity;
import org.iabako.shared.entity.business.Product;
import org.iabako.shared.entity.enumeration.NotificationType;
import org.iabako.shared.entity.enumeration.PriceUnit;
import org.iabako.shared.entity.enumeration.ProductType;
import org.iabako.shared.entity.enumeration.TrackingType;
import org.iabako.shared.iservice.business.ProductServiceAsync;
import org.iabako.shared.tools.GenericTools;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by jose on 16/01/15.
 */
public abstract class ProductForm extends AbstractForm {

    interface MyUiBinder extends UiBinder<HTMLPanel, ProductForm> {
    }

    protected MyUiBinder binderForm = GWT.create(MyUiBinder.class);

    protected final ProductServiceAsync productServiceAsync = ProductServiceAsync.Util.getInstance();

    @UiField
    InputText number;
    @UiField
    InputText name;
    @UiField
    InputTextArea description;
    @UiField
    CheckboxBoolean productType;
    @UiField
    InputTextAmount productPrice;
    @UiField
    InputTextAmount productPurchasePrice;
    @UiField
    InputSwitch taxIncluded;
    @UiField
    HTMLPanel taxInput;
    @UiField
    InputTextAmount taxPercent;
    @UiField
    SelectList productPriceUnit;

    protected ProductForm(PageConfigEnum pageConfigEnum, String explanationMenuLabel) {

        setForm(binderForm, pageConfigEnum, explanationMenuLabel);

        Popup.resizeToSmallPopup();

        setDefaultValues();

        setHandlers();
    }

    private void setDefaultValues() {
        if (this instanceof ProductCreate) {
            productServiceAsync.getNextAvailableId(new IabakoAsyncCallback<String>() {
                public void onSuccess(String result) {
                    number.setValue(result);
                    super.onSuccess(result);
                }
            });
        }
        productServiceAsync.getLastTax(new IabakoAsyncCallback<Double>() {
            public void onSuccess(Double tax) {
                if (taxPercent.getAmountValue() == null && tax != null) {
                    taxPercent.setValue(GenericTools.formatAmount(tax + ""));
                }
                super.onSuccess(tax);
            }
        });

        ListBox unitList = productPriceUnit.getSelectField();
        for (int i = 0; i < unitList.getItemCount(); i++) {
            unitList.setItemText(i, ((PriceUnit) productPriceUnit.getEnumValues().get(i)).getCompleteLabel());
        }
    }

    private void setHandlers() {
        productType.getCheckbox().addValueChangeHandler(new ValueChangeHandler<Boolean>() {
            public void onValueChange(ValueChangeEvent<Boolean> booleanValueChangeEvent) {
                productPurchasePrice.setVisible(productType.getValue());
            }
        });

        taxIncluded.addValueChangeHandler(new ValueChangeHandler() {
            public void onValueChange(ValueChangeEvent valueChangeEvent) {
                taxInput.setVisible(taxIncluded.getValue());
                productPrice.setInputTitle(Messages.getLabel(taxIncluded.getValue() ? "product_form_price_with_tax" : Messages.getLabel("product_form_price")));
            }
        });
    }

    @Override
    protected List<IField> getMandatoryFields() {
        List<IField> mandatoryFields = new ArrayList<IField>();
        mandatoryFields.add(number);
        mandatoryFields.add(name);
        mandatoryFields.add(description);
        mandatoryFields.add(productType);

        if (productType.getValue()) {
            mandatoryFields.add(productPurchasePrice);
        }

        mandatoryFields.add(productPrice);
        mandatoryFields.add(productPriceUnit);
        mandatoryFields.add(taxIncluded);

        if (taxIncluded.getValue()) {
            mandatoryFields.add(taxPercent);
        }

        return mandatoryFields;
    }

    protected void setProduct(Product product) {
        entity = product;

        number.setValue(product.getNumber());
        name.setValue(product.getName());
        description.setValue(product.getDescription());
        productType.setValue(product.getProductType() == ProductType.resale);

        if (productType.getValue()) {
            productPurchasePrice.setValue(GenericTools.formatAmount(product.getPurchasePrice() + ""));
        }

        productPrice.setValue(GenericTools.formatAmount(product.getPrice() + ""));
        productPriceUnit.setEnumValue(product.getPriceUnit());

        if (product.getTaxPercent() != null) {
            taxIncluded.setValue(true);
            taxPercent.setValue(GenericTools.formatAmount(product.getTaxPercent() + ""));
        } else {
            taxIncluded.setValue(false);
        }

        enableAddLinkAction(productServiceAsync);
    }

    @Override
    protected AbstractEntity getEntity() {
        if (entity == null) {
            entity = new Product();
        }
        Product product = (Product) entity;
        product.setNumber(number.getValue());
        product.setName(name.getValue());
        product.setDescription(description.getValue());
        product.setProductType(productType.getValue() ? ProductType.resale : ProductType.manufactured);

        if (productType.getValue()) {
            product.setPurchasePrice(productPurchasePrice.getAmountValue());
        } else {
            product.setPurchasePrice(null);
        }

        product.setPrice(productPrice.getAmountValue());
        product.setPriceUnit((PriceUnit) productPriceUnit.getEnumValue());

        if (taxIncluded.getValue()) {
            product.setTaxPercent(taxPercent.getAmountValue());
        } else {
            product.setTaxPercent(null);
        }

        return product;
    }

    @Override
    public boolean validate() {
        if (!uiValidation()) {
            return false;
        }
        Product product = (Product) serverValidation();
        if (product == null) {
            return false;
        }

        final boolean creation = product.getId() == null;

        productServiceAsync.save(product, new IabakoAsyncCallback<Product>() {
            public void onSuccess(Product result) {
                popup.handleClickClose();

                ValidationMessage validationMessageInPageContent = ValidationMessage.getFromRootPage();
                if (creation) {
                    validationMessageInPageContent.showSuccessMessage("validation_product_form_create_success");
                    AuthenticateUserProvider.getNotificationPanel().refresh(NotificationType.stockRupture);
                    AuthenticateUserProvider.getTrackingPanel().refresh(TrackingType.productNew);
                } else {
                    validationMessageInPageContent.showSuccessMessage("validation_product_form_modify_success");
                    AuthenticateUserProvider.getTrackingPanel().refresh(TrackingType.productModify);
                }

                if (NavigationController.getInstance().getRootPage().pageContentComposite instanceof ProductSearch) {
                    //If rootPage is ServiceSearch, we have to refresh search
                    ((ProductSearch) NavigationController.getInstance().
                            getRootPage().pageContentComposite).productSearchForm.searchForm.search(false);
                }

                super.onSuccess(result);
            }
        });
        return true;
    }
}
